/**
 * 
 */
package idv.takeshi.software.productline.bookstore.infrastructure.persistence.jpa;

import java.util.LinkedHashSet;
import java.util.Set;

import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.lang.Validate;
import org.springframework.stereotype.Repository;

import idv.takeshi.software.productline.bookstore.domain.model.book.Author;
import idv.takeshi.software.productline.bookstore.domain.model.book.AuthorDuplicateException;
import idv.takeshi.software.productline.bookstore.domain.model.book.AuthorRepository;

/**
 * A model repository implementation for AuthorRepository.
 * @author takeshi
 *
 */
@Repository("authorRepository")
public class AuthorRepositoryImpl implements AuthorRepository {
	
	@PersistenceContext
	private EntityManager entityManager;
	
	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.book.AuthorRepository#add(idv.takeshi.software.productline.bookstore.domain.model.book.Author)
	 */
	public void add(Author author) throws AuthorDuplicateException {
		Validate.notNull(author, "author shall always not be null");
		try {
			this.entityManager.persist(author);
		} catch(EntityExistsException  e){
			throw new AuthorDuplicateException("Author:" + author.getName() + " is duplicate");
		}
	}

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.book.AuthorRepository#add(java.util.Set)
	 */
	public void add(Set<Author> authors)  throws AuthorDuplicateException {
		Validate.notEmpty(authors, "authors shall always not be null/empty");
		for(Author author: authors){
			this.add(author);
		}
	}

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.book.AuthorRepository#getAll()
	 */
	@SuppressWarnings("unchecked")
	public Set<Author> getAll() {
		Query query = this.entityManager.createNamedQuery("findAllAuthors");
		Set<Author> authors = new LinkedHashSet<Author>(query.getResultList());
		return authors;
	}

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.book.AuthorRepository#getById(java.lang.Long)
	 */
	public Author getById(Long id) {
		Validate.notNull(id, "id shall always not be null");
		return this.entityManager.find(Author.class, id);
	}

	/* (non-Javadoc)
	 * @see idv.takeshi.software.productline.bookstore.domain.model.book.AuthorRepository#remove(idv.takeshi.software.productline.bookstore.domain.model.book.Author)
	 */
	public void remove(Author author) {
		Validate.notNull(author, "author shall not be null");
		this.entityManager.remove(author);
	}

}
